<?php
/**
 *
 * @author Martin "DevelX" Jurča
 */
class Gallery extends Module {
    protected $name = 'Gallery';
    protected $administrable = true;
    protected $version = '2010-08-15';
    protected $details = array('dependencies' => array(),
            'observes' => array('Gallery'));

    const GALLERIES = 'galleryGalleries';
    const PHOTOS = 'galleryPhotos';

    protected $galleriesTable = array('id' => 'iPN+', 'name' => 'sN',
            'parent' => 'iNI', 'order' => 'iN', 'created' => 'iN',
            'lastEdit' => 'i', 'description' => "v'8192'", 'user' => 'iN');
    protected $photosTable = array('id' => 'iPN+', 'name' => 's', 'user' =>
            'iN', 'description' => "v'4096'", 'gallery' => 'iN', 'created' =>
            'iN', 'lastEdit' => 'i', 'order' => 'iN', 'file' => 'iN');

    protected $galleryRecord = array('table' => self::GALLERIES, 'data' =>
            array());
    protected $photoRecord = array('table' => self::PHOTOS, 'data' =>
            array());

    protected $fileRoot = 5;

    public function __construct(DBAPI $dbapi, RecordList $recordList) {
        parent::__construct($dbapi, $recordList);
        $this->galleryRecord['properties'] = $this->galleriesTable;
        $this->photoRecord['properties'] = $this->photosTable;
    }

    public function install() {
        Modules::getModule('Users')->registerRights($this->getName(),
                $this->getRights());
        return $this->dbdriver->createTable(self::GALLERIES,
                $this->galleriesTable) && $this->dbdriver->
                createTable(self::PHOTOS, $this->photosTable);
    }

    public function uninstall() {
        return $this->dbdriver->dropTable(self::GALLERIES) &&
                $this->dbdriver->dropTable(self::PHOTOS);
    }

    public function getMetaInfo($field, $url) {
        if ($field == 'title') {
            return $this->getMetaInfoTitle($url);
        }
        return '';
    }

    public function getMetaInfoTitle($url) {
        $url = explode('/', $url);
        if (isset($url[1])) {
            if (isset($url[2])) {
                if ($url[1] == 'gallery') {
                    $id = (int) substr($url[2], strrpos($url[2], '-') + 1);
                    $gallery = $this->galleryRecord;
                    $gallery['data']['id'] = $id;
                    $this->dbapi->refresh($gallery);
                    return $gallery['data']['name'];
                }
            }
            return '';
        }
        return $this->getUIName();
    }

    public function onAddGallery(&$details, $source) {
        if (!$this->hasRights('create gallery')) {
            return;
        }
        $user = Modules::getModule('Users')->getUser();
        $gallery = $this->fillRecord($this->galleryRecord, $details);
        $gallery['data']['order'] = 1;
        $gallery['data']['created'] = time();
        $gallery['data']['user'] = $user['data']['id'];
        $cols = array('id', 'order');
        $gals = $this->dbdriver->select(self::GALLERIES, $cols, '`parent` = ' .
                $details['parent']);
        foreach ($gals as $gal) {
            $update = array('order' => $gal['order'] + 1);
            $this->dbdriver->update(self::GALLERIES, $update, '`id` = ' .
                    $gal['id']);
        }
        $this->dbapi->save($gallery);
    }

    public function onEditGallery(&$details, $source) {
        if (!$this->hasRights('edit gallery')) {
            return;
        }
        $gallery = $this->fillRecord($this->galleryRecord, $details);
        $gallery['data']['lastEdit'] = time();
        $changes = array('name' => 1, 'parent' => 1, 'description' => 1,
                'lastEdit' => 1);
        $this->dbapi->update($gallery, $changes);
    }

    public function onAddPhotos(&$details, $source) {
        if (!$this->hasRights('add photo')) {
            return;
        }
        $user = Modules::getModule('Users')->getUser();
        $files = Modules::getModule('Files')->uploadFiles($_FILES,
                $this->fileRoot);
        $toRSS = false;
        if (isset($files[0])) {
            $cols = array('id');
            $order = array();
            $check = &$this->dbdriver->select(self::PHOTOS, $cols,
                    '`gallery` = ' . (int) $details['gallery'], $order, 0, 1);
            $err = $this->dbdriver->getError();
            if ($err != '') {
                trigger_error($err, E_USER_WARNING);
            }
            if (!isset($check[0])) {
                $toRSS = true;
            }
        }
        foreach ($files as &$file) {
            $photo = $this->photoRecord;
            $photo['data'] = array('user' => $user['data']['id'], 'gallery' =>
                    $details['gallery'], 'created' => time(), 'order' =>
                    $this->getMaxPhotoOrder($details['gallery']) + 1, 'file' =>
                    $file['data']['id']);
            $this->dbapi->save($photo);
            if ($toRSS && Modules::getModule('RSS')) {
                $cols = array('name');
                $gallery = &$this->dbdriver->select(self::GALLERIES, $cols,
                        '`id` = ' . (int) $details['gallery']);
                $img = 'http://' . Config::DOMAIN_NAME . Kernel::
                        getSimpleImageLink($file['data']['id'], 80, 80);
                $code = $this->lang('newGallery') . $gallery[0]['name'] .
                        " <img src=\"$img\" alt=\"{$gallery[0]['name']}\" />";
                Modules::getModule('RSS')->pushItem($this->lang('newGallery') .
                        $gallery[0]['name'], 'http://' . Config::DOMAIN_NAME .
                        Config::WEB_DIR . '/galerie/gallery/' . Kernel::
                        createUrl($gallery[0]['name']) . '-' .
                        (int) $details['gallery'] . '/', $code);
                $toRSS = false;
            }
        }
    }

    public function onDeletePhoto(&$details, $source) {
        $cols = array('gallery', 'file');
        $galId = &$this->dbdriver->select(self::PHOTOS, $cols, '`id` = ' .
                (int) $details);
        if (!isset($galId[0])) {
            return;
        }
        Kernel::setRedirect($this->getLink('photos/' . $galId[0]['gallery'] .
                '/'));
        if (!$this->hasRights('delete photo') || !Modules::getModule('Users')->
                checkRights('Files', 'delete files')) {
            return;
        }
        Modules::getModule('Files')->deleteFile($galId[0]['file']);
        $this->dbdriver->delete(self::PHOTOS, '`id` = ' . (int) $details);
        $this->addMsg('photoDeleted', self::MSG_CONFIRM);
    }

    public function onMoveUp(&$details, $source) {
        $cols = array('order', 'gallery');
        $photo = &$this->dbdriver->select(self::PHOTOS, $cols, '`id` = ' .
                (int) $details);
        if (!isset($photo[0])) {
            return;
        }
        Kernel::setRedirect($this->getLink('photos/' . $photo[0]['gallery'] .
                '/'));
        if (!$this->hasRights('edit gallery') || ($photo[0]['order'] <= 1)) {
            return;
        }
        $cols = array('id');
        $up = array();
        $photos = &$this->dbdriver->select(self::PHOTOS, $cols,
                '`gallery` = ' . $photo[0]['gallery'] . ' AND `order` = ' .
                ($photo[0]['order'] - 1));
        foreach ($photos as &$pID) {
            $up[] = $pID['id'];
        }
        if (isset($up[0])) {
            $change = array('order' => $photo[0]['order']);
            $this->dbdriver->update(self::PHOTOS, $change, '`id` IN (' .
                    implode(',', $up) . ')');
        }
        $change = array('order' => $photo[0]['order'] - 1);
        $this->dbdriver->update(self::PHOTOS, $change, '`id` = ' . $details);
        $this->addMsg('orderChanged', self::MSG_CONFIRM);
    }

    public function onMoveDown(&$details, $source) {
        $cols = array('order', 'gallery');
        $photo = &$this->dbdriver->select(self::PHOTOS, $cols, '`id` = ' .
                (int) $details);
        if (!isset($photo[0])) {
            return;
        }
        Kernel::setRedirect($this->getLink('photos/' . $photo[0]['gallery'] .
                '/'));
        if (!$this->hasRights('edit gallery')) {
            return;
        }
        $cols = array('id');
        $down = array();
        $photos = &$this->dbdriver->select(self::PHOTOS, $cols,
                '`gallery` = ' . $photo[0]['gallery'] . ' AND `order` = ' .
                ($photo[0]['order'] + 1));
        foreach ($photos as &$pID) {
            $down[] = $pID['id'];
        }
        if (isset($down[0])) {
            $change = array('order' => $photo[0]['order']);
            $this->dbdriver->update(self::PHOTOS, $change, '`id` IN (' .
                    implode(',', $down) . ')');
        }
        $change = array('order' => $photo[0]['order'] + 1);
        $this->dbdriver->update(self::PHOTOS, $change, '`id` = ' . $details);
        $this->addMsg('orderChanged', self::MSG_CONFIRM);
    }

    public function onMoveGalleryUp(&$details, $source) {
        $galId = (int) $details;
        $cols = array('order');
        $order = &$this->dbdriver->select(self::GALLERIES, $cols, '`id` = ' .
                $galId);
        Kernel::setRedirect($this->getLink());
        $order = $order[0]['order'];
        if (!$this->hasRights('edit gallery') || ($order <= 1)) {
            return;
        }
        $values = array('order' => $order);
        $this->dbdriver->update(self::GALLERIES, $values, '`order` = ' .
                ($order - 1));
        $values['order']--;
        $this->dbdriver->update(self::GALLERIES, $values, '`id` = ' . $galId);
        $this->addMsg('orderChanged', self::MSG_CONFIRM);
    }

    public function onMoveGalleryDown(&$details, $source) {
        $galId = (int) $details;
        $cols = array('order');
        $order = &$this->dbdriver->select(self::GALLERIES, $cols, '`id` = ' .
                $galId);
        Kernel::setRedirect($this->getLink());
        $order = $order[0]['order'];
        $limit = array('MAX(`order`)');
        $limit = &$this->dbdriver->select(self::GALLERIES, $limit);
        $limit = $limit[0]['MAX(`order`)'];
        if (!$this->hasRights('edit gallery') || ($order >= $limit)) {
            return;
        }
        $values = array('order' => $order);
        $this->dbdriver->update(self::GALLERIES, $values, '`order` = ' .
                ($order + 1));
        $values['order']++;
        $this->dbdriver->update(self::GALLERIES, $values, '`id` = ' . $galId);
        $this->addMsg('orderChanged', self::MSG_CONFIRM);
    }

    public function onDeleteGallery($details, $source) {
        Kernel::setRedirect($this->getLink());
        if (!$this->hasRights('delete gallery')) {
            return;
        }
        $galId = (int) $details;
        $cols = array('id', 'file');
        $photos = $this->dbdriver->select(self::PHOTOS, $cols, '`gallery` = ' .
                $galId);
        foreach ($photos as $photo) {
            Modules::getModule('Files')->deleteFile($photo['file']);
            $this->dbdriver->delete(self::PHOTOS, '`id` = ' . $photo['id']);
        }
        $this->dbdriver->delete(self::GALLERIES, '`id` = ' . $galId);
    }
    
    public function initDisplayPublicGallery() {
        Modules::getModule('View')->addJS(Config::WEB_DIR .
                '/utils/lightbox/prototype.js');
        Modules::getModule('View')->addJS(Config::WEB_DIR .
                '/utils/lightbox/scriptaculous.js?load=effects,builder');
        Modules::getModule('View')->addJS(Config::WEB_DIR .
                '/utils/lightbox/lightbox.js');
        Modules::getModule('View')->addCSS(Config::WEB_DIR .
                '/utils/lightbox/lightbox.css');
    }
    
    public function displayPublicGallery($galId) {
        $galId = (int) substr($galId, strrpos($galId, '-') + 1);
        $gallery = array('name');
        $gallery = &$this->dbdriver->select(self::GALLERIES, $gallery,
                '`id` = ' . $galId);
        if (!isset($gallery[0])) {
            return;
        }
        $gallery = $gallery[0]['name'];
        $photos = $this->loadPhotos($galId);
        $cols = array('id', 'name');
        $order = array('order');
        $subgalleries = &$this->dbdriver->select(self::GALLERIES, $cols,
                '`parent` = ' . $galId, $order);
        foreach ($subgalleries as &$subgallery) {
            $this->loadPreview($subgallery);
            $subgallery['link'] = $this->getLink('gallery/' .
                    Kernel::createUrl($subgallery['name']) . '-' .
                    $subgallery['id'] . '/');
        }
        $params = array('gallery' => $gallery, 'photos' => $photos,
                'galleries' => $subgalleries);
        $this->template('gallery-photos', $params);
    }
    
    public function displayPublicIndex() {
        $cols = array('id', 'name');
        $order = array('order');
        $galleries = &$this->dbdriver->select(self::GALLERIES, $cols,
                '`parent` = 0', $order);
        foreach ($galleries as &$gallery) {
            $this->loadPreview($gallery);
            $gallery['link'] = $this->getLink('gallery/' .
                    Kernel::createUrl($gallery['name']) . '-' .
                    $gallery['id'] . '/');
        }
        $params = array('galleries' => &$galleries);
        $this->template('galleries', $params);
    }

    public function displayAdminPhotos($galId) {
        if (!$this->hasRights('edit gallery')) {
            return;
        }
        $cols = array('id', 'name', 'file');
        $order = array('order');
        $photos = &$this->dbdriver->select(self::PHOTOS, $cols,
                '`gallery` = ' . $galId, $order);
        foreach ($photos as &$photo) {
            $photo['moveUp'] = $this->getLink($photo['id'], 'moveUp');
            $photo['moveDown'] = $this->getLink($photo['id'], 'moveDown');
            $photo['delete'] = $this->getLink($photo['id'], 'deletePhoto');
        }
        $params = array('photos' => &$photos);
        $this->template('photos-list', $params);
    }

    public function displayAdminAddPhotos($galId) {
        if (!$this->hasRights('add photo')) {
            return;
        }
        $form = array('start' => 'addPhotos', 'legend' => 'addPhotosForm',
                'submit' => 'add', 'items' => array(array('type' => 'hidden',
                'name' => 'gallery', 'value' => (int) $galId)));
        for ($i = 0; $i < 5; $i++) {
            $form['items'][] = array('type' => 'file', 'label' => 'photo',
                    'name' => 'photo[]');
        }
        $this->prepareFormData($form);
        $params = array('form' => &$form);
        $this->template('form', $params);
    }

    public function displayAdminEditGallery($id) {
        if (!$this->hasRights('edit gallery')) {
            return;
        }
        $gallery = array('name', 'description', 'parent');
        $gallery = &$this->dbdriver->select(self::GALLERIES, $gallery,
                '`id` = ' . (int) $id);
        $gallery = $gallery[0];
        $form = array('start' => 'editGallery', 'legend' => 'editGalleryForm',
                'submit' => 'save', 'items' => array(array('name' =>
                'name', 'label' => 'name', 'value' => $gallery['name']),
                array('name' => 'parent', 'type' => 'select', 'options' =>
                $this->getGalleriesOptions(), 'label' => 'parent',
                'selected' => $gallery['parent']), array('name' =>
                'description', 'label' => 'description', 'type' => 'textarea',
                'cols' => 40, 'rows' => 5, 'value' => $gallery['description']),
                array('name' => 'id', 'type' => 'hidden', 'value' => $id)));
        $this->prepareFormData($form);
        $params = array('form' => &$form);
        $this->template('form', $params);
    }

    public function displayAdminIndex() {
        $cols = array('id', 'order', 'name');
        $order = array('order');
        $gals = &$this->dbdriver->select(self::GALLERIES, $cols, '', $order);
        foreach ($gals as &$gal) {
            $this->loadPreview($gal);
            $gal['add'] = $this->getLink('add-photos/' . $gal['id'] . '/');
            $gal['photos'] = $this->getLink('photos/' . $gal['id'] . '/');
            $gal['edit'] = $this->getLink('edit-gallery/' . $gal['id'] . '/');
            $gal['up'] = $this->getLink($gal['id'], 'moveGalleryUp');
            $gal['down'] = $this->getLink($gal['id'], 'moveGalleryDown');
            $gal['delete'] = $this->getLink($gal['id'], 'deleteGallery');
        }
        $params = array('galleries' => $gals);
        $this->template('list', $params);
    }

    public function displayAdminAddGallery() {
        if (!$this->hasRights('create gallery')) {
            return;
        }
        $form = array('start' => 'addGallery', 'legend' => 'addGalleryForm',
                'submit' => 'create', 'items' => array(array('name' =>
                'name', 'label' => 'name'), array('name' => 'parent', 'type' =>
                'select', 'options' => $this->getGalleriesOptions(), 'label' =>
                'parent'), array('name' => 'description', 'label' =>
                'description', 'type' => 'textarea', 'cols' => 40, 'rows' =>
                5)));
        $this->prepareFormData($form);
        $params = array('form' => &$form);
        $this->template('form', $params);
    }

    public function displayAdminSubmenu() {
        $menu = array(
            array('href' => '', 'label' => 'galleryList'),
            array('href' => 'add-gallery/', 'label' => 'addGallery')
        );
        $this->prepareMenu($menu);
        $params = array('menu' => &$menu);
        $this->template('submenu', $params);
    }

    private function loadPhotos($gallery) {
        $cols = array('file');
        $order = array('order');
        $files = &$this->dbdriver->select(self::PHOTOS, $cols,
                '`gallery` = ' . $gallery, $order);
        foreach ($files as &$file) {
            $file = $file['file'];
        }
        return $files;
    }

    private function getMaxPhotoOrder($gallery) {
        $cols = array('MAX(`order`)');
        $max = &$this->dbdriver->select(self::PHOTOS, $cols,
                '`gallery` = ' . (int) $gallery);
        return $max[0]['MAX(`order`)'];
    }

    private function loadPreview(&$gallery) {
        $cols = array('file');
        $order = array('order');
        $preview = &$this->dbdriver->select(self::PHOTOS, $cols,
                '`gallery` = ' . $gallery['id'], $order, 0, 1);
        if (!isset($preview[0])) {
            $this->loadPreviewFromSubgallery($gallery);
            return;
        }
        $gallery['preview'] = $preview[0]['file'];
    }

    private function loadPreviewFromSubgallery(&$gallery) {
        $col = array('id');
        $order = array('order');
        $subgalleries = $this->dbdriver->select(self::GALLERIES, $col,
                '`parent` = ' . $gallery['id'], $order);
        foreach ($subgalleries as $subgallery) {
            $this->loadPreview($subgallery);
            if ($subgallery['preview']) {
                $gallery['preview'] = $subgallery['preview'];
                return;
            }
        }
        $gallery['preview'] = false;
    }
    
    private function getMaxGalleryOrder($parent) {
        $cols = array('MAX(`order`)');
        $max = &$this->dbdriver->select(self::GALLERIES, $cols, '`parent` = ' .
                (int) $parent);
        return $max[0]['MAX(`order`)'];
    }

    private function getGalleriesOptions() {
        $cols = array('id', 'name');
        $galleries = &$this->dbdriver->select(self::GALLERIES, $cols);
        $options = array(0 => '-');
        foreach ($galleries as &$gallery) {
            $options[$gallery['id']] = $gallery['name'];
        }
        return $options;
    }
}
?>
